﻿using log4net.Appender;
using log4net.Config;
using log4net.Layout;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace JCode
{
    /// <summary>
    /// 依赖:log4net-1.2.13(.net40)
    /// 日志记录文件，用于记录日志.
    /// 1. 日志分为:
    /// DEBUG
    /// INFO
    /// WARNING
    /// ERROR
    /// FAULT
    /// </summary>
    public static class Logger
    {
        private static string s_logOutputDirectory;
        private static Dictionary<string, log4net.ILog> s_loggerDict = new Dictionary<string, log4net.ILog>();
        private static IAppender s_allAppender;

        private const string TAG_ALL = "ALL";
        private static object s_lockObj = new object();

        /// <summary>
        ///  根据日志路径初始化
        /// </summary>
        /// <param name="directory"></param>
        public static void InitByLogDirectory(string directory)
        {
            BasicConfigurator.Configure(GetDebugAppender());

            s_logOutputDirectory = directory;
            s_allAppender = GetRollingFileAppender(s_logOutputDirectory, TAG_ALL);
        }

        /// <summary>
        /// 使用文本记录异常日志
        /// </summary>
        /// <Author>zyzheng</Author>
        /// <date>2014-4-16</date>
        private static RollingFileAppender GetRollingFileAppender(string logDirectory, string tag)
        {
            if (string.IsNullOrEmpty(logDirectory))
            {
                return null;
            }
            string txtLogPath = string.Empty;
            txtLogPath = Path.Combine(logDirectory, tag + "\\");


            RollingFileAppender fileAppender = new RollingFileAppender();
            fileAppender.Name = string.Format("{0}Appender", tag);
            fileAppender.File = logDirectory;// string.Format("{0}{1}\\", logDirectory, tag);
            fileAppender.AppendToFile = true;
            fileAppender.StaticLogFileName = false;
            fileAppender.DatePattern = string.Format("yyyy-MM-dd\"\\\\{0}.log\"", tag);  //"yyyy-MM-dd\"\\.log\"";
            fileAppender.RollingStyle = RollingFileAppender.RollingMode.Composite;
            fileAppender.MaxFileSize = 1024 * 1024;
            fileAppender.MaxSizeRollBackups = 1024;
            fileAppender.LockingModel = new log4net.Appender.FileAppender.MinimalLock();

            PatternLayout patternLayout = new PatternLayout();
            if (!string.Equals(tag, TAG_ALL, StringComparison.CurrentCultureIgnoreCase))
            {
                patternLayout.ConversionPattern = "%d [%t] %p %m %newline";
            }
            else
            {
                patternLayout.ConversionPattern = "%d [%t] %p %logger %m %newline";
            }
            patternLayout.ActivateOptions();
            fileAppender.Layout = patternLayout;

            //选择UTF8编码，确保中文不乱码。
            fileAppender.Encoding = Encoding.UTF8;

            fileAppender.ActivateOptions();
            return fileAppender;
        }

        private static ConsoleAppender GetConsoleAppender()
        {
            ConsoleAppender appender = new ConsoleAppender();
            appender.Name = "ConsoleAppender";

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%d  [%t] %p  %logger %m %newline";
            patternLayout.ActivateOptions();
            appender.Layout = patternLayout;

            appender.ActivateOptions();
            return appender;
        }

        private static IAppender GetDebugAppender()
        {
            DebugAppender appender = new DebugAppender();
            appender.Name = "DebugAppender";

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%d  [%t] %p  %logger %m %newline";
            patternLayout.ActivateOptions();
            appender.Layout = patternLayout;

            appender.ActivateOptions();
            return appender;
        }

        /// <summary>
        /// 获得log4net的日志器
        /// </summary>
        /// <param name="tagUpper"></param>
        /// <returns></returns>
        private static log4net.ILog GetLog(string tag)
        {
            string tagUpper = tag.ToUpper();
            if (s_loggerDict.ContainsKey(tagUpper))
            {
                return s_loggerDict[tagUpper];
            }
            else
            {
                if (string.IsNullOrEmpty(s_logOutputDirectory))
                {
                    return null;
                }
                lock (s_lockObj)
                {
                    if (s_loggerDict.ContainsKey(tagUpper))
                    {
                        return s_loggerDict[tagUpper];
                    }
                    log4net.ILog log = log4net.LogManager.GetLogger(tagUpper);
                    log4net.Repository.Hierarchy.Logger logger = (log4net.Repository.Hierarchy.Logger)log.Logger;
                    logger.Level = logger.Hierarchy.LevelMap[TAG_ALL];
                    if (!string.Equals(tagUpper, TAG_ALL, StringComparison.CurrentCultureIgnoreCase))
                    {
                        logger.AddAppender(GetRollingFileAppender(s_logOutputDirectory, tagUpper));
                    }
                    logger.AddAppender(s_allAppender);
                    s_loggerDict.Add(tagUpper, log);
                    return log;
                }
            }
        }

        #region info
        public static void Info(string message)
        {
            InfoToTag(TAG_ALL, message);
        }

        /// <summary>
        /// 信息日志
        /// </summary>
        /// <param name="tag">获取信息Logger的名字</param>
        /// <param name="message">信息消息</param>
        public static void InfoToTag(string tag, string message)
        {
            log4net.ILog loginfo = GetLog(tag);
            if (loginfo == null)
            {
                return;
            }
            loginfo.Info(message);
        }

        #endregion

        #region debug
        public static void Debug(string message)
        {
            DebugToTag(TAG_ALL, message);
        }

        /// <summary>
        /// 输出日志
        /// </summary>
        /// <param name="tag">获取输出Logger的名字</param>
        /// <param name="message">输出信息</param>
        public static void DebugToTag(string tag, string message)
        {
#if DEBUG
            log4net.ILog logdebug = GetLog(tag);
            if (logdebug == null)
            {
                return;
            }
            logdebug.Debug(message);
#endif
        }

        #endregion

        #region warning
        public static void Warning(string message)
        {
            WarningToTag(TAG_ALL, message);
        }

        /// <summary>
        /// 警告日志
        /// </summary>
        /// <param name="tag">获取警告Logger的名字</param>
        /// <param name="message">警告信息</param>
        public static void WarningToTag(string tag, string message)
        {
            log4net.ILog logwarning = GetLog(tag);
            if (logwarning == null)
            {
                return;
            }
            logwarning.Warn(message);
        }

        #endregion

        #region error

        public static void Error(string message)
        {
            ErrorToTag(TAG_ALL, message);
        }

        /// <summary>
        /// 错误日志
        /// </summary>
        /// <param name="tag">获取错误logger的名字</param>
        /// <param name="message">错误消息</param>
        public static void ErrorToTag(string tag, string message)
        {
            log4net.ILog logerror = GetLog(tag);
            if (logerror == null)
            {
                return;
            }
            logerror.Error(message);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="tag">标签</param>
        /// <param name="message">错误消息</param>
        /// <param name="exception">异常信息</param>
        public static void FaultToTag(string tag, string message, Exception exception)
        {
            log4net.ILog logerror = GetLog(tag);
            if (logerror == null)
            {
                return;
            }
            logerror.Error(string.Format("{0}{1}ex:{2}", message, Environment.NewLine, exception));
        }
        #endregion

        #region fatal

        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="message"></param>
        public static void Fatal(string message)
        {
            FatalToTag(TAG_ALL, message);
        }

        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="tag">标签</param>
        /// <param name="message">错误消息</param>
        public static void FatalToTag(string tag, string message)
        {
            log4net.ILog logerror = GetLog(tag);
            if (logerror == null)
            {
                return;
            }
            logerror.Fatal(message);
        }

        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="tag">标签</param>
        /// <param name="message">错误消息</param>
        /// <param name="exception">异常信息</param>
        public static void FatalToTag(string tag, string message, Exception exception)
        {
            log4net.ILog logerror = GetLog(tag);
            if (logerror == null)
            {
                return;
            }
            logerror.Fatal(string.Format("{0}{1}ex:{2}", message, Environment.NewLine, exception));
        }
        #endregion
    }
}
